package org.jeecg.modules.business.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang3.ObjectUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.TokenUtils;
import org.jeecg.modules.business.dto.BusMeetingRoomScheduleDetailDto;
import org.jeecg.modules.business.dto.BusMeetingRoomScheduleDto;
import org.jeecg.modules.business.entity.*;
import org.jeecg.modules.business.enums.CouponsKeyEnum;
import org.jeecg.modules.business.enums.FeeSubjectType;
import org.jeecg.modules.business.mapper.BusMeetingRoomScheduleMapper;
import org.jeecg.modules.business.service.IBusRoomBookingOrdersService;
import org.jeecg.modules.business.vo.BusMeetingKeyValueVo;
import org.jeecg.modules.business.vo.BusMeetingRoomScheduleDetailVo;
import org.jeecg.modules.business.vo.BusMeetingRoomScheduleVo;
import org.jeecg.modules.business.vo.MeetingRoomScheduleDetailVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * <p>
 * 会议室预定表 服务实现类
 * </p>
 *
 * @author fendo
 * @since 2023-03-15
 */
@Service
public class BusMeetingRoomScheduleServiceImpl extends ServiceImpl<BusMeetingRoomScheduleMapper, BusMeetingRoomSchedule> implements IService<BusMeetingRoomSchedule> {
       @Resource
       private BusMeetingRoomScheduleMapper meetingRoomScheduleMapper;

        @Resource
        private BusMeetingRoomScheduleDetailServiceImpl meetingRoomScheduleDetailService;

        @Resource
        private BusMeetingRoomServiceImpl busMeetingRoomService;

        @Resource
        private BusMeetingRoomScheduleOrderDetailServiceImpl busMeetingRoomScheduleOrderDetailService;
    @Resource
    private IBusRoomBookingOrdersService busRoomBookingOrdersService;

    /**
     *
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Result create(BusMeetingRoomScheduleDto dto){
        DateTimeFormatter struct = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String tenantId = TokenUtils.currentTenantId();
        String hotelId = dto.getHotelId();

        //查询数据库是否有相同的数据
        List<BusMeetingRoomScheduleDetailDto> detailList = dto.getDetailList();
        List<LocalDateTime> dataRange = detailList.stream().map(v -> LocalDate.parse(v.getMeetingDate(),struct).atStartOfDay()).collect(Collectors.toList());
        dataRange.sort(Comparator.naturalOrder());
        LocalDateTime min = dataRange.get(0);
        LocalDateTime max = dataRange.get(dataRange.size() -1);
        max = LocalDateTime.of(max.toLocalDate(), LocalTime.of(23,59,59));;
        List<String> roomIds = detailList.stream().map(v -> v.getMeetingRoomId()).collect(Collectors.toList());
        List<BusMeetingRoomScheduleDetail> detailsList = meetingRoomScheduleDetailService.fetchByDateRange(min,max, hotelId, roomIds);
        /**
         * 创建主表
         */
        BusMeetingRoomSchedule roomSchedule = new BusMeetingRoomSchedule();

        BeanUtil.copyProperties(dto,roomSchedule);
        roomSchedule.setTenantId(tenantId);
        roomSchedule.setCreateTime(LocalDateTime.now());
        roomSchedule.setCreateId(TokenUtils.getAuthUser().getId());
        roomSchedule.setPayType(1);
        roomSchedule.setAmount(new BigDecimal(0));
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        roomSchedule.setOrderNo("HY"+sdf.format(System.currentTimeMillis()));
        meetingRoomScheduleMapper.insert(roomSchedule);

        List<BusMeetingRoomScheduleDetail> details = new ArrayList<>();

        detailList.forEach(v -> {
            LocalDateTime meetingDate = LocalDate.parse(v.getMeetingDate(),struct).atStartOfDay();
            List<BusMeetingRoomScheduleDetail> list = detailsList.stream().filter(f ->{
                if(f.getMeetingRoomId().equals(v.getMeetingRoomId()) && f.getTimeSpan().intValue() == v.getTimeSpan().intValue() && f.getMeetingDate().compareTo(meetingDate) == 0){
                    return true;
                }
                return false;
            }).collect(Collectors.toList());
            if(!CollectionUtil.isEmpty(list)) throw new JeecgBootException("数据重复!");
            BusMeetingRoomScheduleDetail detail= new BusMeetingRoomScheduleDetail();

            detail.setMeetingRoomId(v.getMeetingRoomId());
            detail.setMeetingDate(meetingDate);
            detail.setTimeSpan(v.getTimeSpan().intValue());
            detail.setTenantId(tenantId);
            detail.setMeetingRoomScheduleId(roomSchedule.getId());
            detail.setHotelId(hotelId);
            details.add(detail);
        });
        meetingRoomScheduleDetailService.saveBatchDetail(details);
        return Result.ok("创建成功!");
    }


    /**
     * 查询 创建数据
     * @param startDate
     * @param endDate
     * @return
     */
    public  Result fetch(String startDate,String endDate,String hotelId){
        List<BusMeetingRoomScheduleVo> vos = new ArrayList<>();

        DateTimeFormatter struct = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime startTime = LocalDate.parse(startDate,struct).atStartOfDay();
        LocalDate endLocalDate = LocalDate.parse(endDate,struct);
        LocalDateTime endTime = LocalDateTime.of(endLocalDate, LocalTime.of(23,59,59));;

        DateTimeFormatter struct1 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        List<BusMeetingRoom> busMeetingRooms = busMeetingRoomService.fetch(hotelId);
        if(CollectionUtil.isEmpty(busMeetingRooms)) return Result.ok(vos);
        List<String> meetingIds  = busMeetingRooms.stream().map(v -> v.getId()).collect(Collectors.toList());

        List<BusMeetingRoomScheduleDetail> scheduleDetails =  meetingRoomScheduleDetailService.fetchByDateRange(startTime,endTime, hotelId,meetingIds);

        List<String> scheduleIds =  scheduleDetails.stream().map(v -> v.getMeetingRoomScheduleId()).collect(Collectors.toList());
        List<BusMeetingRoomSchedule> schedules = new ArrayList<>();
        if(!CollectionUtil.isEmpty(scheduleIds)){
            schedules =  meetingRoomScheduleMapper.selectBatchIds(scheduleIds);
        }
        List<BusMeetingRoomSchedule> finalSchedules = schedules;
        busMeetingRooms.forEach(v -> {
            BusMeetingRoomScheduleVo vo = new BusMeetingRoomScheduleVo();
            vo.setMeetingRoomName(v.getName());
            vo.setId(v.getId());
            List<BusMeetingRoomScheduleDetailVo> schedule = new ArrayList<>();

            //获取当前会议室下的所有 预定详情数据
            List<BusMeetingRoomScheduleDetail> details =  scheduleDetails.stream().filter(schedul -> schedul.getMeetingRoomId().equals(v.getId())).collect(Collectors.toList());
            for (int key = 1; key <= CouponsKeyEnum.getDictList().size(); key++) {
                //第二层 上午下午中午
                BusMeetingRoomScheduleDetailVo detailVo = new BusMeetingRoomScheduleDetailVo();
                detailVo.setTimePeriod(CouponsKeyEnum.val(key).getTitle());

                List<BusMeetingKeyValueVo> dataCh = new ArrayList<>();
                //第二层结束
                Map<String, List<MeetingRoomScheduleDetailVo>> map = new HashedMap();
                //查询详情数据
                int finalKey = key;
                List<BusMeetingRoomScheduleDetail> value = details.stream().filter(detail -> detail.getTimeSpan().intValue() == finalKey).collect(Collectors.toList());
                if (!CollectionUtil.isEmpty(value)) {
                    //第三层开始 eg: 上午 ： 上午的所有数据
                    value.forEach(vl -> {
                        MeetingRoomScheduleDetailVo scheduleDetailVo = new MeetingRoomScheduleDetailVo();
                        //生成key
                        String value_key = vl.getMeetingDate().format(struct1);
                        List<MeetingRoomScheduleDetailVo> scheduleDetailVos = new ArrayList<>();
                        //如果存在这个key
                        if (map.containsKey(value_key)) {
                            scheduleDetailVos = map.get(value_key);
                        }
                        Optional<BusMeetingRoomSchedule> scheduleOptional = finalSchedules.stream().filter(sc -> sc.getId().equals(vl.getMeetingRoomScheduleId())).findFirst();
                        if (!scheduleOptional.isPresent()) return;
                        BusMeetingRoomSchedule vl_schedule = scheduleOptional.get();
                        //生成数据
                        scheduleDetailVo.setTheme(vl_schedule.getTheme());
                        scheduleDetailVo.setDetail(vl);
                        scheduleDetailVo.setRoomSchedule(vl_schedule);
                        scheduleDetailVos.add(scheduleDetailVo);
                        map.put(value_key, scheduleDetailVos);
                    });
                    map.forEach((map_k, map_v) -> {
                        BusMeetingKeyValueVo valueVo = new BusMeetingKeyValueVo();
                        valueVo.setKey(map_k);
                        valueVo.setValue(map_v);
                        dataCh.add(valueVo);
                    });
                    detailVo.setSchedule(dataCh);
                }else{
                    detailVo.setSchedule(new ArrayList<>());
                }
                schedule.add(detailVo);
            }
            vo.setChild(schedule);
            vos.add(vo);
        });
        return Result.ok(vos);
    }

    /**
     * 结算
     * @param busMeetingRoomSchedule
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Result settle(BusMeetingRoomSchedule busMeetingRoomSchedule) {
        if (busMeetingRoomSchedule.getPayType().equals(1)) {
            if (ObjectUtils.isEmpty(busMeetingRoomSchedule.getPaymentMethodList())) {
                return Result.error("结算支付方式不能为空");
            }
            BigDecimal sum = busMeetingRoomSchedule.getAmount().subtract(busMeetingRoomSchedule.getPreferentialAmount());
            if (sum.compareTo(BigDecimal.ZERO) < 0) {
                return Result.error("优惠金额不能大于订单金额");
            }
            AtomicReference<BigDecimal> sumAmount = new AtomicReference<>(new BigDecimal(0));
            busMeetingRoomSchedule.getPaymentMethodList().forEach(item -> {
                sumAmount.set(sumAmount.get().add(item.getAmount()));
            });
            if (sumAmount.get().compareTo(sum) != 0) {
                return Result.error("输入必须等于结账应收金额");
            }
        }
        busMeetingRoomSchedule.setBillStatus(1);
        if (busMeetingRoomSchedule.getPayType().equals(2)) {
            if (ObjectUtils.isEmpty(busMeetingRoomSchedule.getSettleRoomOrderNo())) {
                return Result.error("请选择入账人");
            }
            busMeetingRoomSchedule.setBillStatus(2);
        }
        meetingRoomScheduleMapper.updateById(busMeetingRoomSchedule);
        LambdaQueryWrapper<BusMeetingRoomScheduleOrderDetail> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(BusMeetingRoomScheduleOrderDetail::getMeetingRoomScheduleId, busMeetingRoomSchedule.getId());
        busMeetingRoomScheduleOrderDetailService.remove(lambdaQueryWrapper);
        if (busMeetingRoomSchedule.getPayType().equals(2)) {
            List<BusOrderFee> fees = new ArrayList<>();
            BusOrderFee busOrderFee = new BusOrderFee();
            busOrderFee.setMoney(busMeetingRoomSchedule.getAmount());
            busOrderFee.setSubjectType(FeeSubjectType.HUI_YI_SHI.getKey());
            fees.add(busOrderFee);
            busRoomBookingOrdersService.setLivingOrderFee(fees, busMeetingRoomSchedule.getSettleRoomOrderNo(), busMeetingRoomSchedule.getHotelId());
        } else {
            List<BusMeetingRoomScheduleOrderDetail> busMeetingRoomScheduleOrderDetailList = new ArrayList<>();
            busMeetingRoomSchedule.getPaymentMethodList().forEach(item -> {
                if (item.getAmount().compareTo(BigDecimal.ZERO) > 0) {
                    BusMeetingRoomScheduleOrderDetail busMeetingRoomScheduleOrderDetail = new BusMeetingRoomScheduleOrderDetail();
                    busMeetingRoomScheduleOrderDetail.setHotelId(busMeetingRoomSchedule.getHotelId());
                    busMeetingRoomScheduleOrderDetail.setTenantId(busMeetingRoomSchedule.getTenantId());
                    busMeetingRoomScheduleOrderDetail.setMeetingRoomScheduleId(busMeetingRoomSchedule.getId());
                    busMeetingRoomScheduleOrderDetail.setAmount(item.getAmount());
                    busMeetingRoomScheduleOrderDetail.setPayWay(item.getId());
                    busMeetingRoomScheduleOrderDetailList.add(busMeetingRoomScheduleOrderDetail);
                }
            });
            busMeetingRoomScheduleOrderDetailService.saveBatch(busMeetingRoomScheduleOrderDetailList);
        }
        return Result.ok("结算成功!");
    }
}
